package com.cman777.springc.common.helper;

import com.cman777.springc.common.bean.Iface.EnumIFace;
import com.cman777.springc.common.helper.jacksondeserializer.*;
import com.cman777.springc.common.helper.jacksonkeydeserializer.*;
import com.cman777.springc.common.helper.jacksonserializer.*;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.log4j.Log4j2;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.*;

/**
 * @author chenzhicong
 * @time 2019/11/8 1:17
 * @description 全部基于jackson的ObjectMapper, 避免使用不同的json框架由于序列化器、反序列化器不同造成结果不同
 */
@Log4j2
public class JsonHelper{


    /**
     * 这个objectMapper指向MVC使用的objectMapper
     */
    private static volatile ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    static{
        /**
         * 修改ObjectMapper的属性
         */
        OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        OBJECT_MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        handlerObjectMapper4SupportJDK8Time(OBJECT_MAPPER);
    }

    public static ObjectMapper getMvcObjectMapper() {
        return OBJECT_MAPPER;
    }


    public static String toJsonStringQuietly(Object o) {
        try {
            return OBJECT_MAPPER.writeValueAsString(o);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            log.error("ObjectMapper序列化对象失败:{}", e.getMessage());
            return null;
        }
    }


    public static <T> T toObject(@NotBlank String text, Class<T> tClass) {
        try {
            return OBJECT_MAPPER.readValue(text, tClass);
        } catch (Exception e) {
            log.error("ObjectMapper反序列化成对象失败:{}", e.getMessage());
            return null;
        }
    }

    /**
      * 对objectMapper进行时间序列化反序列化的定制
      * 枚举定制
      */
    public static ObjectMapper handlerObjectMapper4SupportJDK8Time(@NotNull ObjectMapper objectMapper) {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
        simpleModule.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE);
        simpleModule.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE);
        simpleModule.addSerializer(Year.class, YearSerializer.INSTANCE);
        simpleModule.addSerializer(YearMonth.class, YearMonthSerializer.INSTANCE);
        simpleModule.addSerializer(MonthDay.class, MonthDaySerializer.INSTANCE);
        simpleModule.addSerializer(EnumIFace.class,new EnumSerializer());

        simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
        simpleModule.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
        simpleModule.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE);
        simpleModule.addDeserializer(YearMonth.class, YearMonthDeserializer.INSTANCE);
        simpleModule.addDeserializer(Year.class, YearDeserializer.INSTANCE);
        simpleModule.addDeserializer(MonthDay.class, MonthDayDeserializer.INSTANCE);
        simpleModule.addDeserializer(Enum.class,new EnumDeserializer());

        simpleModule.addKeyDeserializer(LocalDateTime.class, LocalDateTimeKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(LocalDate.class, LocalDateKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(LocalTime.class, LocalTimeKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(Year.class, YearKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(YearMonth.class, YearMonthKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(MonthDay.class, MonthDayKeyDeserializer.INSTANCE);
        simpleModule.addKeyDeserializer(Enum.class,new EnumKeyDeserializer());

        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

